package com.kzn.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.kzn.entity.*;
import com.kzn.mapper.DetailedTaskMapper;
import com.kzn.mapper.ProjectMapper;
import com.kzn.mapper.PublisherMapper;
import com.kzn.mapper.RoughTaskMapper;
import com.kzn.service.IProjectService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kzn.util.FFmpegUtil;
import com.kzn.util.FileUtils;
import com.kzn.util.ResponseVo;
import com.kzn.util.ZipUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutionException;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author sorclown
 * @since 2022-02-05
 */
@Service
public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> implements IProjectService {
    private RoughTaskMapper roughTaskMapper;
    private DetailedTaskMapper detailedTaskMapper;
    private PublisherMapper publisherMapper;
    private ProjectMapper projectMapper;
    private final static String ROUGH = "rough";
    private final static String DETAILED = "detailed";

    public ProjectServiceImpl() {
    }


    @Autowired
    public ProjectServiceImpl(RoughTaskMapper roughTaskMapper, DetailedTaskMapper detailedTaskMapper, PublisherMapper publisherMapper, ProjectMapper projectMapper) {
        this.roughTaskMapper = roughTaskMapper;
        this.detailedTaskMapper = detailedTaskMapper;
        this.publisherMapper = publisherMapper;
        this.projectMapper = projectMapper;
    }


    @Override
    public boolean checkOverProject() {
        //查询所有project.status为0的项目
        QueryWrapper<Project> projectQueryWrapper = new QueryWrapper<>();
        projectQueryWrapper.eq("status", 0);
        List<Project> projects = projectMapper.selectList(projectQueryWrapper);

        //遍历查询到的项目
        for (Project project : projects) {
            //根据任务类型查询，看是否还有未完成的子任务
            int projectId = project.getId();
            if (ROUGH.equals(project.getParticleSize())) {
                QueryWrapper<RoughTask> roughTaskQueryWrapper = new QueryWrapper<>();
                roughTaskQueryWrapper.eq("status", -1);
                roughTaskQueryWrapper.eq("belongProject", projectId);
                //如果不存在未完成的任务，则将project设为完成。
                if (roughTaskMapper.selectCount(roughTaskQueryWrapper) == 0) {
                    project.setStatus(1);
                    projectMapper.updateById(project);
                    FFmpegUtil.splitVideoByTag(project);
                }

            } else if (DETAILED.equals(project.getParticleSize())) {
                QueryWrapper<DetailedTask> detailedTaskQueryWrapper = new QueryWrapper<>();
                detailedTaskQueryWrapper.eq("status", -1);
                detailedTaskQueryWrapper.eq("belongProject", projectId);
                //如果不存在未完成的任务，则将project设为完成。
                if (detailedTaskMapper.selectCount(detailedTaskQueryWrapper) == 0) {
                    project.setStatus(1);
                    projectMapper.updateById(project);
                }
            }
        }
        return false;
    }

    @Override
    public boolean splitToTask(Project project, int adminId) {
        //获取任务类型
        String particleSize = project.getParticleSize();

        String resourcePath = GlobalVar.UPLOAD_PATH + project.getResourcePath();
        Integer count = 0;
        //获取项目下所有文件，并按照项目需要的类型，分割项目。
        File[] files = new File(resourcePath).listFiles();
        if (ROUGH.equals(particleSize)) {

            //遍历视频，生成粗粒度下的子任务。
            for (File file : files) {
                if (!file.isDirectory()) {
                    count++;
                    RoughTask roughTask = new RoughTask();
                    //设置所属项目
                    roughTask.setBelongProject(project.getId());
                    //设置源文件路径 只保存文件名 全路径为 upload_path + "/" + projectName + "/" + fileName(包括后缀)
                    //结果文件路径为 upload_path + "/" + projectName + "/result/" + Filename.txt
                    roughTask.setSourceFilePath(file.getName());
                    //设置projectName
                    roughTask.setProjectName(project.getProjectName());
                    //设置奖励点数
                    roughTask.setAwardPoint(10);
                    //设置状态
                    roughTask.setStatus(-1);
                    //设置目标
                    roughTask.setTarget(project.getTarget());
                    //将子任务存入数据库
                    roughTaskMapper.insert(roughTask);
                }
            }

        } else if (DETAILED.equals(particleSize)) {
            for (File file : files) {
                if (!file.isDirectory() && !file.getName().equals(".DS_Store")) {

                    //获取视频被切割后，图像存放的位置。
                    String fileName = file.getName().split("\\.")[0];
                    //路径为 upload_path + "/" + projectName + "/image/"
                    String folderPath = resourcePath + "/image/" + fileName;
                    //切割视频
                    if (FFmpegUtil.splitVideoToImage(file.getPath(), folderPath, "jpg", project.getFps())) {
                        //删除源文件
                        file.delete();
                        //遍历存放图片的文件夹，生成对应的任务。
                        File folder = new File(folderPath);
                        File[] inFolders = folder.listFiles();
                        for (File inFolder : inFolders) {
                            if (!inFolder.getName().equals(".DS_Store")) {
                                count++;
                                DetailedTask detailedTask = new DetailedTask();
                                //设置所属项目
                                detailedTask.setBelongProject(project.getId());
                                //设置源文件路径  路径为 upload_path + "/" + projectName + "/image/"  + [filename + "/" + pictureName]
                                //设置结果文件夹路径 路径为 upload_path + "/" + projectName + "/result/" + [filename + "/" + pictureName]
                                detailedTask.setSourceFilePath(fileName + "/" + inFolder.getName());
                                //设置projectName
                                detailedTask.setProjectName(project.getProjectName());
                                //设置每秒帧数
                                detailedTask.setFps(project.getFps());
                                //设置奖励点数
                                detailedTask.setAwardPoint(1);
                                //设置状态
                                detailedTask.setStatus(-1);
                                //设置目标
                                detailedTask.setTarget(project.getTarget());
                                //将子任务存入数据库
                                detailedTaskMapper.insert(detailedTask);
                            }
                        }
                    }
                }
            }

        } else {
            return false;
        }

        //设置子任务的数量
        project.setCount(count);
        project.setStatus(0);
        project.setAdminId(adminId);
        projectMapper.updateById(project);
        return true;
    }

    @Override
    public Double getProjectPercentage(Integer projectId, String particleSize) {
        if (DETAILED.equals(particleSize)) {
            QueryWrapper<DetailedTask> detailedTaskQueryWrapper = new QueryWrapper<>();
            detailedTaskQueryWrapper.eq("belongProject", projectId);
            detailedTaskQueryWrapper.eq("status", 1);
            Long over = detailedTaskMapper.selectCount(detailedTaskQueryWrapper);

            Integer count = projectMapper.selectById(projectId).getCount();
            Double res = Double.valueOf(over) / count;
            return res;

        } else if (ROUGH.equals(particleSize)) {

            QueryWrapper<RoughTask> roughTaskQueryWrapper = new QueryWrapper<>();
            roughTaskQueryWrapper.eq("belongProject", projectId);
            roughTaskQueryWrapper.eq("status", 1);
            Long over = roughTaskMapper.selectCount(roughTaskQueryWrapper);

            Integer count = projectMapper.selectById(projectId).getCount();
            Double res = Double.valueOf(over) / Double.valueOf(count);
            return res;
        }
        return null;
    }


    @Override
    public boolean insertOne(Project project, int publisherId) {
        QueryWrapper<Publisher> wrapper = new QueryWrapper<>();
        wrapper.eq("id", publisherId);
        boolean publisherExists = publisherMapper.exists(wrapper);
        if (publisherExists) {
            QueryWrapper<Project> projectQueryWrapper = new QueryWrapper<>();
            projectQueryWrapper.eq("projectName", project.getProjectName());
//            projectQueryWrapper.eq("publisherId", project.getPublisherId());
            if (!projectMapper.exists(projectQueryWrapper)) {
                projectMapper.insert(project);
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }


    @Override
    public boolean uploadResource(Integer projectId, MultipartFile multipartFile) {
        Project project = projectMapper.selectById(projectId);

        //获取 project 名称
        String projectName = project.getProjectName();

        // 设置保存路径
        // 保存路径：项目路径/uploadResource/{projectName}
        File parentPath = new File(GlobalVar.UPLOAD_PATH + "/" + projectName);
        if (!parentPath.exists()) {
            parentPath.mkdirs();
        }

        // 设置文件保存名 包含路径、文件后缀
        File dest = new File(parentPath.getPath() + "/" + multipartFile.getOriginalFilename());

        try {
            //文件保存
            multipartFile.transferTo(dest);

            // 解压dest文件到parent路径
            ZipUtils.unzip(dest.getPath(), parentPath.getPath());

            // 删除压缩包。
            dest.delete();

            String resourcePath = "/" + projectName;

            //设置 project 资源保存路径, 路径为 upload_path + "/" + projectName,数据库中为 "/" + projectName
            project.setResourcePath(resourcePath);
            //路径为 upload_path + "/" + projectName + "/result",数据库中保存为 "/" + projectName + "/result"
            project.setResultPath(resourcePath + "/result/");
            projectMapper.updateById(project);

            return true;
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }


        return false;
    }

    @Override
    public String getResultByProjectId(Integer projectId, String type, HttpServletResponse res) {
        Project project = projectMapper.selectById(projectId);
        String particleSize = project.getParticleSize();
        String target = project.getTarget();
        String[] targets = target.trim().split(",");
        if ("rough".equals(particleSize)) {
            String resultPath = GlobalVar.UPLOAD_PATH + "/" + project.getProjectName() + "/download";
            try {
                ZipUtils.zipFileTree(new File(resultPath), "zip");
            } catch (IOException e) {
                e.printStackTrace();
            }
            File projectResult = new File(resultPath + ".zip");
            FileUtils.responseTo(projectResult, res);
            projectResult.delete();
            return "success";

        } else if ("detailed".equals(particleSize)) {
            String resultPath = null;
            if ("YOLO".equals(type)) {
                resultPath = GlobalVar.UPLOAD_PATH + "/" + project.getProjectName() + "/result";
            } else if ("VOC".equals(type)) {
                resultPath = GlobalVar.UPLOAD_PATH + "/" + project.getProjectName() + "/result_xml";

            } else if ("CSV".equals(type)) {
                resultPath = GlobalVar.UPLOAD_PATH + "/" +project.getProjectName() + "/result_csv.csv";
                FileUtils.responseTo(new File(resultPath), res);
                return "success";
            }
            try {
                ZipUtils.zipFileTree(new File(resultPath), "zip");
            } catch (IOException e) {
                e.printStackTrace();
            }
            File projectResult = new File(resultPath + ".zip");
            FileUtils.responseTo(projectResult, res);
            projectResult.delete();
            return "success";

        }

        return null;
    }

    @Override
    public String getResourceById(Integer projectId, HttpServletResponse res) {
        Project project = projectMapper.selectById(projectId);
        String sourcePath = GlobalVar.UPLOAD_PATH + "/" + project.getProjectName() + "/image";

        try {
            ZipUtils.zipFileTree(new File(sourcePath),"zip");
        } catch (IOException e) {
            e.printStackTrace();
        }
        File projectSource = new File(sourcePath + ".zip");
        FileUtils.responseTo(projectSource, res);
        projectSource.delete();
        return "success";


    }


}


